package com.doordu.soa.service.web.auth.interceptor;

import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import com.alibaba.fastjson.JSONException;
import com.doordu.soa.service.comm.ResultCode;
import com.doordu.soa.service.web.expection.DataNullException;
import com.doordu.soa.service.web.expection.ForceOfflineException;
import com.doordu.soa.service.web.expection.GzipException;
import com.doordu.soa.service.web.expection.JSONDefineException;
import com.doordu.soa.service.web.expection.NoLoginException;
import com.doordu.soa.service.web.expection.NoPermissionException;
import com.doordu.soa.service.web.expection.OperateTypeException;

/**
 * Created by zjp on 2017/4/19.
 */
@ControllerAdvice
public class GlobalExceptionHandler {

	private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

	@ExceptionHandler(value = { BindException.class })
	public ResponseEntity<ErrorInfo> handleBeanBindException(HttpServletRequest req, BindException bindEx) {
		logger.error("参数绑定异常", bindEx);
		String allErroFields = bindEx.getBindingResult().getFieldErrors().stream().map(FieldError::getField)
				.collect(Collectors.joining(",", "[", "]"));
		ErrorInfo err = new ErrorInfo("参数类型不正确或超出范围, 校验失败字段:" + allErroFields);
		return ResponseEntity.ok(err);
	}

	@ExceptionHandler(value = com.alibaba.fastjson.JSONException.class)
	public ResponseEntity<ErrorInfo> handleJsonException(HttpServletRequest req, JSONException jsonEx) {
		logger.error("参数类型不正确", jsonEx);
		ErrorInfo err = new ErrorInfo("参数类型不正确或超出范围");
		return ResponseEntity.ok(err);
	}

	@ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
	public ResponseEntity<ErrorInfo> handleMethodArgumentTypeMismatchException(HttpServletRequest req,
			Exception defaultEx) {
		ErrorInfo err = new ErrorInfo("请求参数类型不匹配");
		return ResponseEntity.ok(err);
	}

	@ExceptionHandler(value = { HttpRequestMethodNotSupportedException.class, TypeMismatchException.class })
	public ResponseEntity<ErrorInfo> handleHttpRequestMethodNotSupportedException(HttpServletRequest req,
			Exception defaultEx) {
		ErrorInfo err = new ErrorInfo("请求方式出错");
		return ResponseEntity.ok(err);
	}

	@ExceptionHandler(value = NoLoginException.class)
	public ResponseEntity<ErrorInfo> noLoginException(HttpServletRequest req, Exception defaultEx) {
		ErrorInfo err = new ErrorInfo(ResultCode.errmap.get(ResultCode.ERROR_NOT_LOGIN));
		err.setCode(ResultCode.ERROR_NOT_LOGIN);
		// logger.error("请先登录", defaultEx);
		return ResponseEntity.ok(err);
	}

	@ExceptionHandler(value = NoPermissionException.class)
	public ResponseEntity<ErrorInfo> noPermissionException(HttpServletRequest req, Exception defaultEx) {
		ErrorInfo err = new ErrorInfo(ResultCode.errmap.get(ResultCode.ERROR_NOAUTH));
		err.setCode(ResultCode.ERROR_NOAUTH);
		logger.error("权限不足", defaultEx);
		return ResponseEntity.ok(err);
	}

	@ExceptionHandler(value = Exception.class)
	public ResponseEntity<ErrorInfo> handlDefaultException(HttpServletRequest req, Exception defaultEx) {
		logger.error("内部服务器错误", defaultEx);
		ErrorInfo err = new ErrorInfo(defaultEx.getMessage());
		return ResponseEntity.ok(err);
	}

	@ExceptionHandler(value = ForceOfflineException.class)
	public ResponseEntity<ErrorInfo> handlForceOfflineException(HttpServletRequest req, Exception defaultEx) {
		logger.error("该用户已被强制下线或在别处登录", defaultEx);
		ErrorInfo err = new ErrorInfo(defaultEx.getMessage());
		err.setCode(ResultCode.ERROR_FORCE_LOGOUT);
		return ResponseEntity.ok(err);
	}

	@ExceptionHandler(value = GzipException.class)
	public ResponseEntity<ErrorInfo> handlGzipException(HttpServletRequest req, Exception defaultEx) {
		logger.error("上报数据的压缩类型错误", defaultEx);
		ErrorInfo err = new ErrorInfo(defaultEx.getMessage());
		err.setCode(ResultCode.ERROR_GZIP);
		return ResponseEntity.ok(err);
	}

	@ExceptionHandler(value = OperateTypeException.class)
	public ResponseEntity<ErrorInfo> handlOperateTypeException(HttpServletRequest req, Exception defaultEx) {
		logger.error("上报数据的同步类型错误", defaultEx);
		ErrorInfo err = new ErrorInfo(defaultEx.getMessage());
		err.setCode(ResultCode.ERROR_OPERATETYPE);
		return ResponseEntity.ok(err);
	}
	
	@ExceptionHandler(value = JSONDefineException.class)
	public ResponseEntity<ErrorInfo> handlJSONException(HttpServletRequest req, Exception defaultEx) {
		logger.error("上报数据的data的JSON格式错误", defaultEx);
		ErrorInfo err = new ErrorInfo(defaultEx.getMessage());
		err.setCode(ResultCode.ERROR_JSON);
		return ResponseEntity.ok(err);
	}

	
	@ExceptionHandler(value = DataNullException.class)
	public ResponseEntity<ErrorInfo> handlDataNullxception(HttpServletRequest req, Exception defaultEx) {
		logger.error("上报数据体data不能为空", defaultEx);
		ErrorInfo err = new ErrorInfo(defaultEx.getMessage());
		err.setCode(ResultCode.ERROR_DATANULL);
		return ResponseEntity.ok(err);
	}
}
